﻿using System.Linq;

using ARCHFORME.Common.Domain;
using ARCHFORME.Core.Persistance.Common;

using NHibernate;
using NHibernate.Linq;

namespace ARCHFORME.Core.Persistance.NHibernate
{
    internal class NHibernateRepository<T> : Repository<T> where T : class, IEntity
    {
        private readonly ISession session;
        private IQueryable<T> queryable;
        private ISession originalSession;

        public NHibernateRepository(ISession session)
        {
            this.session = session;
        }

        /// <summary>
        ///   Provides access to the repository-specific LINQ-enabled NHibernate collection.
        /// </summary>
        /// <remarks>
        ///   <typeparam name = "T" />.
        /// </remarks>
        protected override IQueryable<T> Entities
        {
            get
            {
                // In cases that a reference to a repositoy is maintained over multiple post-backs, the session belonging to the
                // queryable will be invalid (closed). This results in an exception when performing queries on the queryable.
                // This behaviour is caused by keeping the queryable in a variable. To workaround this problem, we create a new
                // queryable when the current session is a different one that we originally created the queryable with.
                if ((queryable == null) || (originalSession != session))
                {
                    originalSession = session;
                    queryable = session.Query<T>();
                }

                return queryable;
            }
        }

        public override void Add(T entity)
        {
            session.Save(entity);
        }

        public override void Remove(T entity)
        {
            session.Delete(entity);
        }
    }
}